// Copyright tang.  All rights reserved.
// https://gitee.com/inrgihc/dbswitch
//
// Use of this source code is governed by a BSD-style license
//
// Author: tang (inrgihc@126.com)
// Date : 2020/1/2
// Location: beijing , china
/////////////////////////////////////////////////////////////
package com.sondertara.joya.migration.provider.write;

import com.sondertara.common.text.StringUtils;
import com.sondertara.joya.core.JoyaJdbc;
import com.sondertara.joya.core.jdbc.support.dialect.SqlDialect;
import com.sondertara.joya.core.jdbc.support.dialect.SqlDialectRegister;
import com.sondertara.joya.migration.provider.AbstractCommonProvider;
import com.sondertara.joya.migration.provider.ProductFactoryProvider;
import lombok.extern.slf4j.Slf4j;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
public class DefaultTableDataWriteProvider
        extends AbstractCommonProvider
        implements TableDataWriteProvider {

    protected JoyaJdbc jdbcTemplate;
    protected String schemaName;
    protected String tableName;

    protected SqlDialect sqlDialect;
    protected Map<String, Integer> columnType;

    public DefaultTableDataWriteProvider(ProductFactoryProvider factoryProvider) {
        super(factoryProvider);
        this.jdbcTemplate = new JoyaJdbc(factoryProvider.getDataSource());
        this.schemaName = null;
        this.tableName = null;
        this.columnType = null;
        SqlDialectRegister.findOrCreate(factoryProvider.getProductType());
    }

    protected String getPrepareInsertTableSql(List<String> fieldNames) {
        String fullTableName = sqlDialect.tableName(false, null, schemaName, tableName);
        return String.format("INSERT INTO %s ( %s ) VALUES ( %s )",
                fullTableName,
                fieldNames.stream().map(s -> sqlDialect.fmtName(false, s)).collect(Collectors.joining(",")),
                StringUtils.join(Collections.nCopies(fieldNames.size(), "?"), ","));
    }

    @Override
    public void prepareWrite(String schemaName, String tableName, List<String> fieldNames) {
        this.columnType = getTableColumnMetaData(schemaName, tableName, fieldNames);
        if (this.columnType.isEmpty()) {
            throw new RuntimeException(
                    String.format("获取表:%s.%s 的字段的元信息时失败. 请联系 DBA 核查该库、表信息.",
                            schemaName, tableName));
        }
        this.schemaName = schemaName;
        this.tableName = tableName;
    }

    @Override
    public long write(List<String> fieldNames, List<Object[]> recordValues) {
        if (recordValues.isEmpty()) {
            return 0;
        }
        String sqlInsert = getPrepareInsertTableSql(fieldNames);
        int[] argTypes = new int[fieldNames.size()];
        for (int i = 0; i < fieldNames.size(); ++i) {
            String col = fieldNames.get(i);
            argTypes[i] = this.columnType.get(col);
        }

        try {
            jdbcTemplate.batchUpdate(sqlInsert, recordValues, argTypes);
            int affectCount = recordValues.size();
            recordValues.clear();
            if (log.isDebugEnabled()) {
                log.debug("{} insert data affect count: {}", getProductType(), affectCount);
            }
            return affectCount;
        } catch (Exception e) {
            throw e;
        }
    }


}
